package edu.fub.pub2search.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import edu.fub.pub2search.app.util.JSONUtil;
import edu.fub.pub2search.db.CircularRangeFilter;
import edu.fub.pub2search.db.DataAccess;
import edu.fub.pub2search.geo.GeoCalculator;
import edu.fub.pub2search.geo.GeoPosition;

/**
 * A servlet implementation for Pub2Search service. The service requires some parameters
 * such as: latitude (x), longitude (y) and radius size (r).
 * 
 * @author Josef
 */
public class PubSearcher extends HttpServlet {
	
	/** Serial version ID */
	private static final long serialVersionUID = 1L;
	
	/** Data access to help querying */
	private DataAccess dataAccess;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public PubSearcher() {
    	
    	try {
			// get the connection to the MySQL database
			Class.forName("com.mysql.jdbc.Driver").newInstance();
			String url = "jdbc:mysql://localhost/pub2search";
			Connection conn = DriverManager.getConnection(url, "root", "josejose");
			
			// set the data access
			dataAccess = new DataAccess(conn);
		} catch (Exception e) {
			
			e.printStackTrace();
		}		
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) 
		throws ServletException, IOException {
		
		int x = Integer.parseInt(request.getParameter("x"));
		int y = Integer.parseInt(request.getParameter("y"));
		double r = Double.parseDouble(request.getParameter("r"));
		
		// query the pubs.
		List<Map<String, String>> pubList = getPubWithinRadius(x, y, r);
		
		// convert into JSON string.
		String jsonString = JSONUtil.getJsonStringFromList(pubList);
		
		// output stream for writing data on the client side.
		PrintWriter out = response.getWriter();
		out.print(jsonString);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) 
		throws ServletException, IOException {
		
		super.doPost(request, response);
	}

// --------------- PRIVATE METHODS ------------------	
	
	/*
	 * The pub searcher service.
	 */
	private List<Map<String, String>> getPubWithinRadius(int latitude, int longitude, double radius) {
		
		GeoPosition source = new GeoPosition(latitude, longitude);
				
		// mark the outside points of the circle.
		GeoPosition p0 = GeoCalculator.destinationPosition(source, 0, radius);
		GeoPosition p1 = GeoCalculator.destinationPosition(source, 90, radius);
		GeoPosition p2 = GeoCalculator.destinationPosition(source, 180, radius);
		GeoPosition p3 = GeoCalculator.destinationPosition(source, 270, radius);
					
		// query to the database.
		ResultSet queryResult =  dataAccess.queryPub(p0.x, p2.x, p1.y, p3.y);

		// set up the filter.
		CircularRangeFilter filter = new CircularRangeFilter(source, radius);
		List<Map<String, String>> pubList = filter.evaluate(queryResult);
		
		return pubList;		
	}
}
